package com.foodev.maven.gwt;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.maven.plugin.MojoExecutionException;
import org.codehaus.plexus.util.FileUtils;

/**
 * Helper class to extract the native libs zip.
 * 
 * @author Martin Algesten
 */
public class NativeLibsExtractor {

    /**
     * Extracts the native libs from the .zip found on the classpath.
     * 
     * @throws MojoExecutionException
     */
    public void extractNativeLibs(URL url) throws MojoExecutionException, IOException {

        if (url == null)
            throw new MojoExecutionException("No classloader is of type URLClassLoader");

        if (!"file".equals(url.getProtocol())) {
            throw new MojoExecutionException("Native library zip is not a " + "file URL: " + url.toString());
        }

        File dir = new File(url.getPath()).getParentFile();

        ZipInputStream zip = new ZipInputStream(url.openStream());
        ZipEntry entry;
        byte[] buf = new byte[1024];
        int read;

        // Clean up any previous unpack.
        while ((entry = zip.getNextEntry()) != null) {

            File outFile = new File(dir, entry.getName());

            if (outFile.exists()) {
                if (outFile.isDirectory()) {
                    FileUtils.deleteDirectory(outFile);
                } else {
                    outFile.delete();
                }
            }

        }

        zip.close();
        zip = new ZipInputStream(url.openStream());

        while ((entry = zip.getNextEntry()) != null) {

            File outFile = new File(dir, entry.getName());

            File parentDir = entry.isDirectory() ? outFile : outFile.getParentFile();

            if (!parentDir.exists() && !parentDir.mkdirs())
                throw new RuntimeException("Failed to make dir: " + parentDir.getAbsolutePath());

            if (!entry.isDirectory()) {

                FileOutputStream fos = new FileOutputStream(outFile);

                while ((read = zip.read(buf)) != -1)
                    fos.write(buf, 0, read);

                outFile.setLastModified(entry.getTime());

                fos.close();
            }

        }

    }


}
